/*
 * Copyright 2008 Claudius Hauptmann
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.claudiushauptmann.gwt.multipage.rebind;

import java.io.PrintWriter;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.claudiushauptmann.gwt.multipage.client.MultipageEntryPoint;
import com.google.gwt.core.ext.Generator;
import com.google.gwt.core.ext.GeneratorContext;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JPackage;
import com.google.gwt.core.ext.typeinfo.TypeOracle;

public class EntryPointFactoryImplGenerator extends Generator {
	private Log log = LogFactory.getLog(EntryPointFactoryImplGenerator.class);

	@Override
	public String generate(TreeLogger logger, GeneratorContext context,
			String typeName) throws UnableToCompleteException {

		PrintWriter pw = context.tryCreate(logger,
				"com.claudiushauptmann.gwt.multipage.client",
				"EntryPointFactoryImpl");

		if (pw != null) {
			pw.println("package com.claudiushauptmann.gwt.multipage.client;");
			pw.println();
			pw.println("import com.google.gwt.core.client.GWT;");
			pw.println("import com.google.gwt.core.client.RunAsyncCallback;");
			pw.println("import com.google.gwt.core.client.EntryPoint;");
			pw.println("import com.google.gwt.user.client.Window;");
			pw.println("import com.claudiushauptmann.gwt.multipage.client.core.EntryPointFactory;");

			pw.println();
			pw.println("public class EntryPointFactoryImpl"
					+ " implements EntryPointFactory {");
			pw.println();
			pw.println("	public void onModuleLoad() {");

			TypeOracle oracle = context.getTypeOracle();
			JPackage[] packages = oracle.getPackages();

			pw.println("		String moduleBaseURL = GWT.getModuleBaseURL();");
			pw.println("		String href = Window.Location.getHref();");
			pw.println();
			pw
					.println("		int endIndex = moduleBaseURL.lastIndexOf(\"/\", moduleBaseURL.length()-2);");
			pw
					.println("		String relativePath = href.substring(endIndex+1, href.length());");
			pw.println();

			for (JPackage pack : packages) {

				JClassType[] classes = pack.getTypes();

				for (JClassType classtype : classes) {
					MultipageEntryPoint mep = classtype
							.getAnnotation(MultipageEntryPoint.class);

					if (mep != null) {
						log.info(classtype.getQualifiedSourceName());

						pw.println("		if (relativePath.matches(\""
								+ mep.urlPattern() + "\")) {");
						pw.println("			GWT.runAsync(new RunAsyncCallback() {");
						pw
								.println("				public void onFailure(Throwable caught) {");
						pw
								.println("					Window.alert(\"Code download failed\");");
						pw.println("				}");
						pw.println("				public void onSuccess() {");
						pw.println("					EntryPoint ep = new "
								+ classtype.getQualifiedSourceName() + "();");
						pw.println("					ep.onModuleLoad();");
						pw.println("				}");
						pw.println("			});");
						pw.println("		}");
					}
				}
			}

			pw.println("	}");
			pw.println();
			pw.println("}");

			context.commit(logger, pw);
		}

		return "com.claudiushauptmann.gwt.multipage.client.EntryPointFactoryImpl";
	}

}
